package org.projectback.service.AccountService.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.projectback.entity.AccountEntity.Account;
import org.projectback.entity.AccountEntity.dataTransferObject.emailMessageDTO;
import org.projectback.entity.AccountEntity.viewObject.RegisterVO;
import org.projectback.entity.AccountEntity.viewObject.ResetVO;
import org.projectback.service.AccountService.AccountService;
import org.projectback.service.SqlService.impl.SqlServiceImpl;
import org.projectback.utils.Utils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;


import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;

@Service
public class AccountServiceImpl implements AccountService {

    @Resource
    private AmqpTemplate amqpTemplate;
    @Resource
    private SqlServiceImpl sqlServiceImpl;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private Utils utils;


    /**
     * 邮件队列发送器(生产者)
     *
     * @param email               用户注册填写的邮箱
     * @param type                注册类型:1.register 2.reset
     * @param stringRedisTemplate redis缓存
     * @return Success
     */
    @Override
    public String emailQueueSender(String email, String type, StringRedisTemplate stringRedisTemplate) {
        try {
            RandomGenerator random = RandomGeneratorFactory.of("Xoroshiro128PlusPlus").create();
            //生成六位数验证码
            int code = random.nextInt(899999) + 100000;
            emailMessageDTO emailMessageDTO = new emailMessageDTO(code, email, type);
            //将处理添加到队列等待 监听器处理
            amqpTemplate.convertAndSend("email", emailMessageDTO);
            //根据类型进行内存缓存
            switch (type) {
                case "register":
                    stringRedisTemplate.opsForValue().set("registered-email-code:" + email, String.valueOf(code), 1, TimeUnit.MINUTES);
                case "reset":
                    stringRedisTemplate.opsForValue().set("reset-email-code:" + email, String.valueOf(code), 3, TimeUnit.MINUTES);
            }
            return null;
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    /**
     * @param registerVO          前端发送的实体类封装
     * @param stringRedisTemplate redis
     * @return 返回注册结果
     */
    @Override
    public String registerAccount(RegisterVO registerVO, StringRedisTemplate stringRedisTemplate) {

        String username = registerVO.getUsername();
        String password = passwordEncoder.encode(registerVO.getPassword());
        String email = registerVO.getEmail();
        //获取缓存中的验证码
        String code = stringRedisTemplate.opsForValue().get("registered-email-code:" + email);
        if (Objects.isNull(code)) return "请先获取验证码";
        //比对验证码
        if (!code.equals(registerVO.getCode())) return "验证码错误请重新输入";
        //先验证用户名 以及邮箱是否已经在数据库中
        if (existAccountByUserName(username)) {
            return "用户名重复";
        }
        if (existAccountByEmail(email)) {
            return "邮箱重复";
        }
        Account account = new Account(username, email, null, password, "user");
        if (sqlServiceImpl.save(account)) {
            stringRedisTemplate.delete("registered-email-code:" + email);
            return null;
        } else {
            return "注册失败,联系管理员!";
        }
    }

    /**
     * @param email 验证邮箱有效性
     * @return null:!null
     */
    @Override
    public String confirmAccount(String email) {
        if (existAccountByEmail(email)) {
            return null;
        }
        return "用户不存在!";
    }

    @Override
    public String resetAccount(ResetVO resetVO, StringRedisTemplate stringRedisTemplate) {
        //获取修改信息
        String password = passwordEncoder.encode(resetVO.getPassword());
        String email = resetVO.getEmail();
        //先获取验证码
        String code = stringRedisTemplate.opsForValue().get("reset-email-code:" + email);
        if (Objects.isNull(code)) return "请先获取验证码";
        //验证码判断
        if (!code.equals(resetVO.getCode())) return "验证码错误请重新输入";
        //判断密码是否和数据库重复？
        boolean duplicate = sqlServiceImpl.query().eq("email", email).one().getPassword().equals(password);
        if (duplicate) {
            return "密码不能与前密码一致!请重新输入";
        }
        //尝试修改数据库
        try {
            UpdateWrapper<Account> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("email", email).set("password", password);
            boolean result = sqlServiceImpl.update(updateWrapper);
            if (result) {
                stringRedisTemplate.delete("reset-email-code:" + email);
                return null;
            }else {
                return "系统故障,请联系管理员!";
            }
        }catch (Exception e){
            return e.getMessage();
        }
    }

    private boolean existAccountByUserName(String username) {
        return sqlServiceImpl.exists(Wrappers.<Account>query().eq("username", username));
    }

    private boolean existAccountByEmail(String email) {
        return sqlServiceImpl.exists(Wrappers.<Account>query().eq("email", email));
    }
}
